import { ConfigSvr } from './config';
import { Injectable } from '@angular/core';
import { OrderConfig } from './../models/kdsConfig';
import { Devices } from './../models/devices';
import { TimeManager } from './../utils/timeManager';
import { GrowlMessageType, MessageBoxService } from './../components/messageBox';
import { Order, Orderitem } from './../models/order';
import * as moment from 'moment';
import * as lodash from 'lodash';
import axios from 'axios';
//  Immutable
import { Observable, BehaviorSubject, ReplaySubject, Subject } from 'rxjs';

export enum OrderPriority {
    normal,
    high,
    extremeHigh
}

export interface AdsAbout {
    retCode: Number;
    version: string;
    ads_id: string;
    name: string;
    url: string;
    adapterIds: Array<any>;
}

export class ServiceBaseX {
    constructor() {

    }
    public generateExpeditionOrderSerialNo() {
        return this.getOfFBS("/api/expeditionOrders/serialNO");
    }
    public getServerTime() {
        return this.getOfFBS("/api/system/getServerTime");
    }
    protected fbsHeartbeat(ip?) {
        //todo 暂时
        const protocol = this.iSSSL ? "https://" : "http://";
        const url = protocol + (ip || this.LDCConfig.ip) + ":" + this.fbsPort + "/api/system/getStoreId";
        return this.get(url)
    }
    protected ldcHeartbeat(ip?) {
        //todo 暂时
        const protocol = this.iSSSL ? "https://" : "http://";
        const url = protocol + (ip || this.LDCConfig.ip) + ":" + this.fbsPort + "/api/system/getStoreId";
        return this.get(url)
    }
    set currentDevice(currentDevice: Devices) {
        localStorage.setItem("currentDevice", JSON.stringify(currentDevice));
    }
    get currentDevice(): Devices {
        let currentDevice = localStorage.getItem("currentDevice");
        if (currentDevice) {
            return JSON.parse(currentDevice);
        }
        return null;
    }
    set currentKitchenSolutions(currentKitchenSolutions: any) {
        localStorage.setItem("currentKitchenSolutions", JSON.stringify(currentKitchenSolutions));
    }
    get currentKitchenSolutions(): any {
        let currentKitchenSolutions = localStorage.getItem("currentKitchenSolutions");
        if (currentKitchenSolutions) {
            return JSON.parse(currentKitchenSolutions);
        }
        return null;
    }
    set adsAbout(adsAbout: AdsAbout) {
        localStorage.setItem("adsAbout", JSON.stringify(adsAbout));
    }
    get adsAbout(): AdsAbout {
        let adsAbout = localStorage.getItem("adsAbout");
        if (adsAbout) {
            return JSON.parse(adsAbout);
        }
        return null;
    }
    public get LDCConfig() {
        let config = localStorage.getItem("ldcconfig");
        if (config) {
            return JSON.parse(config);
        }
        return null;
    }
    public set LDCConfig(LDCConfig) {
        localStorage.setItem("ldcconfig", JSON.stringify(LDCConfig));
    }

    public set store(store) {
        localStorage.setItem("store", JSON.stringify(store));
    }
    public get store() {
        let resStore = localStorage.getItem("store");
        if (resStore) {
            return JSON.parse(resStore);
        }
        return null;
    }
    public get token() {
        let resStore = localStorage.getItem("user");
        if (resStore) {
            return JSON.parse(resStore).token;
        }
        return null;
    }
    public set user(user) {
        localStorage.setItem("user", JSON.stringify(user));
    }
    public get user() {
        let resStore = localStorage.getItem("user");
        if (resStore) {
            return JSON.parse(resStore).user;
        }
        return null;
    }
    set terminal(value) {
        localStorage.setItem("terminal", JSON.stringify(value));
    }
    get terminal() {
        let terminal = localStorage.getItem("terminal");
        if (terminal) {
            return JSON.parse(terminal);
        } else {
            return null;
        }
    }

    private get iSSSL(): boolean { return location.protocol.indexOf("https") > -1; }
    private get fbsHost() {
        const ip = this.LDCConfig && this.LDCConfig.ip;
        const protocol = this.iSSSL ? "https://" : "http://";
        return protocol + ip;
    }
    private get fbsPort() {
        return this.iSSSL ? 8886 : 8887;
    }
    private get fbsAddress() {
        return this.fbsHost + ":" + this.fbsPort;
    }
    get cloudAddress(): string {
        //Nginx代理使用相对地址，不使用Nginx服务代理，需要指向绝对服务器地址
        return "http://192.168.1.222";
    }
    protected async postOfClound(url, body) {

    }
    protected get cloudHost() {
        return "http://192.168.1.222"
    }

    private httpResultCallback(result): Promise<any> {
        return new Promise((resolve, reject) => {
            result.then(response => {
                const rData = response.data;
                if (rData.code == 200) resolve(rData.data);
                else reject(rData.message);
            }).catch(error => {
                reject("本地数据中心网络错误");
            })
        });
    }
    protected getOfFBS(url) {
        const newUrl = this.fbsAddress + url;
        return this.get(newUrl);
    }
    protected postOfFBS(url, body) {
        const newUrl = this.fbsAddress + url;
        return this.post(newUrl, body);
    }
    protected axiosGet(url) {
        return axios.get(url)
    }
    protected get(url, config?) {
        const axiosGetResponse = config ? axios.get(url, config) : axios.get(url);
        return this.httpResultCallback(axiosGetResponse);
    }
    protected post(url, body?) {
        body&&(body.user = this.user)
        body&&(body.terminal = this.terminal);
        const token = this.token;
        const storeId = this.store&&this.store.id;
        return this.httpResultCallback(axios.post(url, body || {},{headers:{
            token,storeId
        }}))
    }
}


export class OrderSvr extends ServiceBaseX {
    constructor() {
        super();
    }

    public async getOrders() {
        try {
            const res = await this.getOfFBS(`/api/kitchenOrders?finishTime=0&stalls=` + this.currentKitchenSolutions.map(x => x.id).join("&stalls="));
            //todo 对code的判断？？ 异常一层一层的抛出
            return res;
        } catch (error) {
            throw new Error(error.message || error)
        }

    }
    public getFinishedOrdersByStall() {
        const beginFinishTime = moment().startOf('day').subtract(1, 'days').valueOf();
        const endFinishTime = TimeManager.current.getServerTime();
        const url = "beginFinishTime=" + beginFinishTime + "&" + "endFinishTime=" + endFinishTime + "&limit=20&sortby=finishTime&order=finishTime";
        return this.getOfFBS("/api/kitchenOrders?stalls=" + this.currentKitchenSolutions.map(x => x.id).join("&stalls=") + "&" + url)
    }
    public getOrdersByStall(stall) {
        return this.getOfFBS(`/api/kitchenOrders?stalls=` + stall);
    }
    public async completeOrder(id: string, itemIds: string[]) {
        try {
            return await this.postOfFBS('/api/kitchenOrders/' + id + "/finish", { itemIds, stalls: this.currentKitchenSolutions.map(x => x.id) });
        } catch (error) {
            throw new Error(error.message || error)
        }
    }
    public async closeOrderItemsByItemsId(id: string, itemIds: string[]) {
        try {
            return await this.postOfFBS('/api/kitchenOrders/' + id + "/close", { itemIds });
        } catch (error) {
            throw new Error(error.message || error)
        }
    }

    public async completeOrderItem(orderId: string, itemId: string) {
        const res = await this.postOfFBS('/api/kitchenOrders/' + orderId + "/cartItems/" + itemId + "/finish", {});
        return res;
    }
    public async completeBranchOrderItems(orderId: string, itemIds: string[]): Promise<Order> {
        const res = await this.postOfFBS('/api/kitchenOrders/' + orderId + '/cartItems/batch/finish', { itemIds });
        return res;
    }

    public async incompleteOrderItem(orderId: string, itemId: string) {
        const res = await this.postOfFBS('/api/kitchenOrders/' + orderId + "/cartItems/" + itemId + "/unFinish", {})
        return res;
    }

    public calcPriorityByElapsedTime(elapsedTime: number, orderConfig: OrderConfig): OrderPriority {
        const priority = elapsedTime / 60;
        if (priority < orderConfig.newOrderTiming) {
            return OrderPriority.normal;
        } else if (priority < orderConfig.timeoutTiming) {
            return OrderPriority.high
        } else {
            return OrderPriority.extremeHigh
        }
    }
    public async addOrder(order): Promise<any> {
        try {
            const res = await this.postOfFBS('/api/kitchenOrders/', { kitchenOrder: order, stalls: this.currentKitchenSolutions.map(x => x.id) })
            return res;
        } catch (error) {
            MessageBoxService.current.Growl(GrowlMessageType.Error, error.message || error, error.message || error);
            throw new Error(error.message || error)
        }
    }

    public deliverExpeditionOrder(order) {
        return this.postOfFBS('/api/expeditionOrders/', { order })
    }

    public cancelDeliverExpeditionOrder(order){
        return this.postOfFBS('/api/expeditionOrders/'+order.id+"/cancel", { order })
    }

    public getExpeditedExpeditionOrders() {
        return this.getOfFBS('/api/expeditionOrders?status=expedited&status=delivered&sortby=expediteBeginTime&sourceTerminalIds=' + this.currentDevice.id);
    }
}